package Dynamic;

import Annotation.Column;
import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @author Jimmy Zhan WORKSTATION
 * @date 2023/4/3 14:55
 * 说明：反射的动态性
 */

public class ReflectTest {

    // 静态
    public Person getInstance(){
        return new Person();
    }

    /**
     * 反射的动态性 / 通用性
     * 举例一：创建对象
     */
    public <T> T getInstance(String className) throws Exception {
        // 获取Class的实例，需要传入全类名
        Class<?> clazz = Class.forName(className);

        // 获取构造器
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);

        // 构造对象
        // constructor.newInstance() 默认的是Object类型，因此需要做一个T类泛型的强转
        return (T)constructor.newInstance();
    }

    @Test
    public void test1() throws Exception {
        // 静态方法
        Person p1 = getInstance();
        System.out.println(p1);

        // 动态方法
        String className = "Dynamic.Person";
        Person p2 = getInstance(className);
        System.out.println(p2);

        String className1  = "java.util.Date";
        Date d1 = getInstance(className1);
        System.out.println(d1);
    }

    /**
     * 反射的动态性 / 通用性
     * 举例二：调用方法
     */
    public Object invoke(String className, String methodName) throws Exception{

        // 1. 创建全类名对应的运行时类的对象
        Class<?> clazz = Class.forName(className);
        Constructor<?> con = clazz.getDeclaredConstructor();
        con.setAccessible(true);

        Object obj = con.newInstance();

        // 2. 获取运行时类中的指定方法并调用
        Method method = clazz.getDeclaredMethod(methodName);
        method.setAccessible(true);
        return method.invoke(obj);
    }

    @Test
    public void test2() throws Exception {
        String className = "Dynamic.Person";
        String methodName = "show";
        System.out.println(invoke(className, methodName));
    }
}
